package config

import (
	"log"
	"os"
	"strconv"
	"strings"

	"github.com/joho/godotenv"
)

type Config struct {
	Server   ServerConfig
	Database DatabaseConfig
	JWT      JWTConfig
	App      AppConfig
	COS      COSConfig
	Upload   UploadConfig
	SMS      SMSConfig
	Redis    RedisConfig
}

type ServerConfig struct {
	Port string
	Mode string
}

type DatabaseConfig struct {
	Driver       string
	Host         string
	Port         int
	Username     string
	Password     string
	Name         string
	Charset      string
	MaxOpenConns int
	MaxIdleConns int
}

type JWTConfig struct {
	Secret      string
	ExpireHours int
}

type AppConfig struct {
	Name    string
	Version string
}

type COSConfig struct {
	SecretID   string
	SecretKey  string
	Region     string
	Bucket     string
	Domain     string
	PathPrefix string
}

type UploadConfig struct {
	MaxFileSize     int64
	AllowedTypes    []string
	ImageQuality    int
	ThumbnailWidth  int
	ThumbnailHeight int
}

type SMSConfig struct {
	SecretID      string
	SecretKey     string
	AppID         string
	Region        string
	SignName      string
	TemplateID    string
	ExpireMinutes int
}

type RedisConfig struct {
	Host        string
	Port        int
	Password    string
	DB          int
	MaxIdle     int
	MaxActive   int
	IdleTimeout int
}

func Load() *Config {
	if err := godotenv.Load(); err != nil {
		log.Println("Warning: .env file not found or could not be loaded:", err)
	}

	return &Config{
		Server: ServerConfig{
			Port: getEnv("SERVER_PORT", "8200"),
			Mode: getEnv("GIN_MODE", "debug"),
		},
		Database: DatabaseConfig{
			Driver:       getEnv("DB_DRIVER", "mysql"),
			Host:         getEnv("DB_HOST", "localhost"),
			Port:         getEnvAsInt("DB_PORT", 3306),
			Username:     getEnv("DB_USER", "root"),
			Password:     getEnv("DB_PASSWORD", "root"),
			Name:         getEnv("DB_NAME", "fuye_api_db"),
			Charset:      getEnv("DB_CHARSET", "utf8mb4"),
			MaxOpenConns: getEnvAsInt("DB_MAX_OPEN_CONNS", 100),
			MaxIdleConns: getEnvAsInt("DB_MAX_IDLE_CONNS", 10),
		},
		JWT: JWTConfig{
			Secret:      getEnv("JWT_SECRET", "dev-jwt-secret-key"),
			ExpireHours: getEnvAsInt("JWT_EXPIRE_HOURS", 24),
		},
		App: AppConfig{
			Name:    getEnv("APP_NAME", "fuye-api API"),
			Version: getEnv("APP_VERSION", "1.0.0"),
		},
		COS: COSConfig{
			SecretID:   getEnv("COS_SECRET_ID", "dev-cos-secret-id"),
			SecretKey:  getEnv("COS_SECRET_KEY", "dev-cos-secret-key"),
			Region:     getEnv("COS_REGION", "ap-guangzhou"),
			Bucket:     getEnv("COS_BUCKET", "dev-bucket"),
			Domain:     getEnv("COS_DOMAIN", "https://dev-bucket.cos.ap-guangzhou.myqcloud.com"),
			PathPrefix: getEnv("COS_PATH_PREFIX", "uploads"),
		},
		Upload: UploadConfig{
			MaxFileSize:     getEnvAsInt64("UPLOAD_MAX_FILE_SIZE", 10485760),
			AllowedTypes:    getEnvAsSlice("UPLOAD_ALLOWED_TYPES", []string{"jpg", "jpeg", "png", "gif", "webp"}),
			ImageQuality:    getEnvAsInt("UPLOAD_IMAGE_QUALITY", 85),
			ThumbnailWidth:  getEnvAsInt("UPLOAD_THUMBNAIL_WIDTH", 300),
			ThumbnailHeight: getEnvAsInt("UPLOAD_THUMBNAIL_HEIGHT", 300),
		},
		SMS: SMSConfig{
			SecretID:      getEnv("SMS_SECRET_ID", "dev-sms-secret-id"),
			SecretKey:     getEnv("SMS_SECRET_KEY", "dev-sms-secret-key"),
			AppID:         getEnv("SMS_APP_ID", "1400000000"),
			Region:        getEnv("SMS_REGION", "ap-guangzhou"),
			SignName:      getEnv("SMS_SIGN_NAME", "开发签名"),
			TemplateID:    getEnv("SMS_TEMPLATE_ID", "1234567"),
			ExpireMinutes: getEnvAsInt("SMS_EXPIRE_MINUTES", 10),
		},
		Redis: RedisConfig{
			Host:        getEnv("REDIS_HOST", "localhost"),
			Port:        getEnvAsInt("REDIS_PORT", 6379),
			Password:    getEnv("REDIS_PASSWORD", ""),
			DB:          getEnvAsInt("REDIS_DB", 0),
			MaxIdle:     getEnvAsInt("REDIS_MAX_IDLE", 10),
			MaxActive:   getEnvAsInt("REDIS_MAX_ACTIVE", 100),
			IdleTimeout: getEnvAsInt("REDIS_IDLE_TIMEOUT", 300),
		},
	}
}

func getEnv(key, defaultValue string) string {
	if value := os.Getenv(key); value != "" {
		return value
	}
	return defaultValue
}

func getEnvAsInt(key string, defaultValue int) int {
	if value := os.Getenv(key); value != "" {
		if intValue, err := strconv.Atoi(value); err == nil {
			return intValue
		}
	}
	return defaultValue
}

func getEnvAsInt64(key string, defaultValue int64) int64 {
	if value := os.Getenv(key); value != "" {
		if intValue, err := strconv.ParseInt(value, 10, 64); err == nil {
			return intValue
		}
	}
	return defaultValue
}

func getEnvAsSlice(key string, defaultValue []string) []string {
	if value := os.Getenv(key); value != "" {
		return strings.Split(value, ",")
	}
	return defaultValue
}
